package org.wddsicmd.widgets;
 
import org.wddsicmd.app.CodeEditorMain;
import org.wddsicmd.app.ButtonTabComponent;
import org.wddsicmd.dev.AndroidDeviceManager;
import org.wddsicmd.util.CustomProperties;
import org.wddsicmd.util.ResourceBundleUtil;
import org.wddsicmd.util.Log;
import org.wddsicmd.util.Resource;
import org.wddsicmd.widgets.OperationButton;

import java.lang.Object;

import java.io.*;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.util.*;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
import java.util.ArrayList;
import java.util.List;

import java.awt.*;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.Insets;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.Image;
import java.awt.event.*;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.Timer;
import javax.swing.JTable;
import javax.swing.table.*;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.Icon;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.TreeModelListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.border.EmptyBorder;
//import javax.swing.text.Document;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;

import javax.swing.Icon;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicTabbedPaneUI;
import javax.swing.plaf.basic.BasicGraphicsUtils;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.jdom2.input.SAXBuilder; 

public class LCDPanel extends JPanel  implements ActionListener {
      private final static String TAG = "LCDPanel";
	  
/* doom-2015-11-4 15:14:33 
      public final static String USER_DIR_DEFAULT = "MSS/USER";	  
 doom-2015-11-4 15:14:33 */
      private final static String LCDPanelXML = "LCDPanel.xml";

/* doom-2015-11-4 15:19:15 
	private final static String LCDPANEL_LOCAL_PATH = "/sdcard/MSS/";
 doom-2015-11-4 15:19:15 */
	//private final static String TEST_DRIVER_DEFAULT = "/sys/devices/platform/sublcd/driver/";
	//private final static String TEST_DRIVER_DEFAULT = "/sys/devices/platform/autoload/driver/";
	private final static String TEST_DRIVER_DEFAULT = "/sdcard/MSSLcdTest/driver/";
	private String LCDPANEL_DRIVER_PATH = TEST_DRIVER_DEFAULT;

	private final static int mVerticalCellMaxCount = 15;
	private final static int mHorizontalCellMaxCount = 8;
	private final static int mVerticalFuncCellMaxCount = 10;

	private final static int mSingleFileMaxLine = 30;
	private final static int mSplitFileCount = 8;

	private int mFuncSelectedItem = 0;
	private String mCurrentOpenFile;

	private String[] mFuncTitleList = new String[] { 
		"Version", 
		"LCDTiming",
		"IDsetting",
		"LCDinit",
		"LCDsuspend",
		"LCDResume",
		"LCDPoweron",
		"LCDPoweroff",
		"HSwrite",
		"HSread"
	};

	private String[] mLCDTimingItems = new String[] {
		"HSA", 
		"VSA",
		"MODE",
		"LANE",
		"VSYNC",
		"VBP",
		"VFP",
		"HSYNC",
		"HBP",
		"HFP",
		"DIV1",
		"DIV2",
		"DIV"		
	};
	   
	private String[] mOperationTitleList = new String[] {
		"OPEN"
		,"SAVE"
		,"SAVE AS"
		,"RUN"
		,"SEND"
	};	

/* doom-2015-10-29 10:18:4 
	private ResourceBundleUtil mLabels;
 doom-2015-10-29 10:18:4 */
	private Resource mResource;
      private CustomProperties mProperties;

	private String[] mFuncCache;
	private String[] mFuncLCDTimingCache;  

	private List<OperationButton> mFuncBtnList = new ArrayList<OperationButton>();
	private List<OperationButton> mOperationBtnList = new ArrayList<OperationButton>();

	private JTextArea mEditArea;
	private JScrollPane mEditAreaScrollPane;
	private JTextArea mLogArea;
	private JScrollPane mLogAreaScrollPane;
	private JTextField mTestDriverFilePath;
	private TextFieldGroup mTextFieldGroup;
/* doom-2015-10-30 15:0:7 
	private JTextField[] mLCDTimingTextFieldGroup;
 doom-2015-10-30 15:0:7 */

	private JLabel mCurrentOpenFileLabel;
	private CodeEditorMain mCodeEditorMain;

	/*private PrintStream mPrintStream;*/
	private Process mLogExportProcess;
	private boolean mLogExporting = false;

	public LCDPanel(CodeEditorMain cem, String titleStr){
		super();
		mCodeEditorMain = cem;
		initLabels();

/* doom-2015-10-29 11:31:1 
		String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
		Log.d(TAG, "###### LCDPanel path: "+ path);
 doom-2015-10-29 11:31:1 */

		mProperties = new CustomProperties();
/* doom-2015-10-29 11:8:16 
		mProperties.setValue("LCDPanel_init", "true");
 doom-2015-10-29 11:8:16 */

		mProperties.readValue("current_open_file"); 
/* doom-2015-10-30 11:49:27 
		mProperties.setValue("current_open_file", "DOOM2");    
		mProperties.getValue("current_open_file");     
 doom-2015-10-30 11:49:27 */


		setLayout(null);
		setBackground(Resource.getBackgroundColor());
		addComponentListener(new ComponentAdapter() {
			@Override
			public void componentResized(ComponentEvent e) {
				onComponentResized();
			}
		});			
/* doom-2015-10-27 10:3:34 
		setBorder(BorderFactory.createEmptyBorder(50,50,50,50));
		setBorder(BorderFactory.createLineBorder(Resource.getForegroundColor()));
 doom-2015-10-27 10:3:34 */

/* doom-2015-10-27 14:6:37 
		JLabel testLabel = new JLabel(titleStr);
		testLabel.setBackground(Resource.getHighlightColor());
		testLabel.setBounds(new Rectangle(0, 0 , 200, 200));
		add(testLabel);
 doom-2015-10-27 14:6:37 */

		btnListInit();
		editAreaInit();
		infoAreaInit();

		dataInit();

		/*mPrintStream = new PrintStream(new CustomOutputStream());
		System.setOut(mPrintStream);
		System.setErr(mPrintStream);*/
	}

	private void adbCmdExecForLog(String cmdStr){

		if(mCodeEditorMain != null){
			String deviceName = mCodeEditorMain.getConnectedDevice();
			if(deviceName == null || deviceName.equals("")){
				Log.d(TAG, "adbCmdExecForLog CAN'T FIND ANY DEVICE");
				return;
			}
		}
		
		try {			
			mLogExportProcess = Runtime.getRuntime().exec(cmdStr);  
			
			final BufferedReader batchInputStream = new BufferedReader(new InputStreamReader(mLogExportProcess.getInputStream()));
			final  BufferedReader  batchErrorReader = new BufferedReader(new InputStreamReader(mLogExportProcess.getErrorStream()));
			
			new Thread(new Runnable() {
				String line;
				public void run() {
					try {
						while((line=batchErrorReader.readLine()) != null) {
							Log.d("adbCmdExecForLog Err", line);	       		        
						}
					} catch (IOException e) {
						e.printStackTrace(); 
						Log.d("adbCmdExecForLog Err exception", e.toString());	     
					}
					Log.d("adbCmdExecForLog Err", "Exit");
					mLogExporting = false;
				}
			}).start();
			
			new Thread(new Runnable() {
				String line;
				public void run() {
					try {
						while((line=batchInputStream.readLine()) != null) {
							//Log.d("adbCmdExecForLog ", line);
							//if(line.contains("lm3630"))
							{
								mLogArea.append(line + AndroidDeviceManager.getLineSeparator());
								mLogArea.setCaretPosition(mLogArea.getText().length());		
							}
							
						}
					} catch (IOException e) {
						e.printStackTrace();  
						Log.d("adbCmdExecForLog exception", e.toString());	
					}
					Log.d("adbCmdExecForLog", "Exit");
					mLogExporting = false;
				}
			}).start();
			
			//int i = process.waitFor();
			mLogExporting = true;
		} catch (Exception e) {
			e.printStackTrace();
		}	
	}	

	private void logExportToTextArea(){
		if(!mLogExporting){
			adbCmdExecForLog(AndroidDeviceManager.getAdbPath() + " shell cat /proc/kmsg");
		}
	}

	/*public class CustomOutputStream extends OutputStream{
		public void write(int arg0) throws IOException {
		}    

		public void write(byte data[]) throws IOException{
			mLogArea.append(new String(data));
		}

		public void write(byte data[], int off, int len) throws IOException {
			mLogArea.append(new String(data, off, len));
			mLogArea.setCaretPosition(mLogArea.getText().length());
		}
	}*/

	private void btnListInit(){
		for(int index = 0; index < mFuncTitleList.length; index++){ 
			OperationButton jb = new OperationButton(mFuncTitleList[index]);
			jb.setActionCommand(mFuncTitleList[index]);
			jb.addActionListener(this);			
			mFuncBtnList.add(jb);
			add(jb);
		}
		for(int index = 0; index < mOperationTitleList.length; index++){ 
			OperationButton jb = new OperationButton(mOperationTitleList[index]);
			jb.setActionCommand(mOperationTitleList[index]);
			jb.addActionListener(this);
			jb.setButtonStyle(1);
			jb.setButtonColor(Color.WHITE, Color.WHITE, Color.BLACK, Color.BLACK, 0.4f, 0.8f);
/* doom-2015-10-30 15:58:36 
			jb.setButtonComponentColor(Color.BLACK, Color.BLACK, Color.WHITE);
 doom-2015-10-30 15:58:36 */
			mOperationBtnList.add(jb);
			add(jb);
		}

		
	}

	private void editAreaInit(){
		mEditArea = new JTextArea("Please input here.");
 		mEditAreaScrollPane = new JScrollPane(mEditArea);
		mEditAreaScrollPane.setVisible(false);
		add(mEditAreaScrollPane);	

		mLogArea = new JTextArea("Log Area");
 		mLogAreaScrollPane = new JScrollPane(mLogArea);
		mLogAreaScrollPane.setVisible(true);
		add(mLogAreaScrollPane);
/* doom-2015-10-30 15:0:3 
		mLCDTimingTextFieldGroup = new JTextField[mLCDTimingItems.length];
 doom-2015-10-30 15:0:3 */
 		mTextFieldGroup = new TextFieldGroup(mLCDTimingItems);
		mTextFieldGroup.setVisible(false);
		add(mTextFieldGroup);	

		mTestDriverFilePath = new JTextField(TEST_DRIVER_DEFAULT);
		mTestDriverFilePath.setVisible(false);
		add(mTestDriverFilePath);	
	}

	private void infoAreaInit(){
		mCurrentOpenFileLabel = new JLabel("");
		mCurrentOpenFileLabel.setVerticalAlignment(JTextField.BOTTOM);
		add(mCurrentOpenFileLabel);		
	}

	private void dataInit(){
		String selectedItemStr = mProperties.readValue("current_selected_item");
		try{
			mFuncSelectedItem = Integer.parseInt(selectedItemStr);
		}catch (NumberFormatException e) {
			mFuncSelectedItem = 0;
		}
			
		mCurrentOpenFile = mProperties.readValue("current_open_file");
		if(mCurrentOpenFile != null && !mCurrentOpenFile.equals("")){
			File currentFile = new File(mCurrentOpenFile);
			if(currentFile.exists()){
				mCurrentOpenFileLabel.setText("[Current open file: " + mCurrentOpenFile+"]");
				loadFileHandler(mCurrentOpenFile);
			}else{
				setEmptyCache();
			}
		}else{
			setEmptyCache();
		}
	}

	protected void initLabels() {
/* doom-2015-10-29 10:18:0 
		mLabels = ResourceBundleUtil.getLAFBundle("org.wddsicmd.res.Labels");
 doom-2015-10-29 10:18:0 */
		mResource = new Resource("org.wddsicmd.res.Labels");
	}	
	public String getStringFromLabels(String key){
/* doom-2015-10-29 10:18:9 
		return Resource.getStringFromLabels(mLabels, key);
 doom-2015-10-29 10:18:9 */
 		return mResource.getStringFromLabels(key);
	}

	public void onComponentResized(){
		int width = getWidth();
		int height = getHeight();


/* doom-2015-11-2 14:58:14 
		Log.d(TAG, "onComponentResized width: "+ width);
		Log.d(TAG, "onComponentResized height: "+ height);
 doom-2015-11-2 14:58:14 */


		/* left side function buttons and operation buttons area */
		int paddingTop = 10;
		int paddingBottom = 50;
		int cellVerticalGap = 2;
		int cellHorizontalGap = 10; 
		int cellWidth = (width - (mHorizontalCellMaxCount - 1) * cellHorizontalGap) / mHorizontalCellMaxCount;
		int cellHeight = (height - paddingTop - paddingBottom - (mVerticalCellMaxCount - 1) * cellVerticalGap) / mVerticalCellMaxCount;

		for(int index = 0; index < mFuncBtnList.size(); index++){ 
			if(index >= mVerticalFuncCellMaxCount){
				mFuncBtnList.get(index).setBounds(new Rectangle(cellWidth + cellHorizontalGap, paddingTop + (cellHeight + cellVerticalGap) * (index - mVerticalFuncCellMaxCount), cellWidth, cellHeight));		
			}else{
				/*if(index == mFuncBtnList.size() - 1 ||
					index == mFuncBtnList.size() - 2){
					mFuncBtnList.get(index).setBounds(new Rectangle(0, paddingTop + (cellHeight + cellVerticalGap) * (index + 1), cellWidth, cellHeight));	
				}else*/
				{
					mFuncBtnList.get(index).setBounds(new Rectangle(0, paddingTop + (cellHeight + cellVerticalGap) * index, cellWidth, cellHeight));		
				}
			}
		}
		
		for(int index = 0; index < mOperationTitleList.length; index++){ 
			mOperationBtnList.get(index).setBounds(new Rectangle(0, paddingTop + (cellHeight + cellVerticalGap) * (index/*+1*/+mFuncBtnList.size()), cellWidth, cellHeight));			
		}

		/* edit area */
		mTestDriverFilePath.setBounds(new Rectangle((cellWidth + cellHorizontalGap) * 0, height - paddingBottom - cellHeight - cellHeight - cellVerticalGap, cellWidth * 3 + 2 * cellHorizontalGap, cellHeight));
		
		int editAreaWidth = (width/2);
		int editAreaHeight = (height - paddingTop - paddingBottom);
		mEditAreaScrollPane.setBounds(new Rectangle(cellWidth+cellHorizontalGap, paddingTop, editAreaWidth, editAreaHeight));
		mTextFieldGroup.setBounds(new Rectangle(cellWidth+cellHorizontalGap, paddingTop, editAreaWidth, editAreaHeight));
		mTextFieldGroup.onComponentResized();
		/* log area */
		int logAreaWidth = width - editAreaWidth - cellWidth - 2* cellHorizontalGap;
		mLogAreaScrollPane.setBounds(new Rectangle(width - logAreaWidth, paddingTop, logAreaWidth, editAreaHeight));

		/* info area */
		int infoAreaWidth = width;
		int infoAreaHeight = 30;
		mCurrentOpenFileLabel.setBounds(new Rectangle(0, height - paddingBottom, infoAreaWidth, infoAreaHeight));		
	}

	private void setFuncSelectedItem(int item){
		
/* doom-2015-10-29 18:26:28 
		Log.d(TAG, "setFuncSelectedItem mFuncSelectedItem: "+ mFuncSelectedItem);
 doom-2015-10-29 18:26:28 */
		mFuncBtnList.get(mFuncSelectedItem).setStatusSelected(false);
		mFuncSelectedItem = item;
/* doom-2015-10-29 18:26:29 
		Log.d(TAG, "setFuncSelectedItem mFuncSelectedItem: "+ mFuncSelectedItem);
 doom-2015-10-29 18:26:29 */
		mFuncBtnList.get(mFuncSelectedItem).setStatusSelected(true);

		String elementName = mFuncTitleList[item];
		if(elementName.equals("LCDTiming")){
/* doom-2015-10-30 15:30:11 
			String textStr = mFuncCache[item];
			mEditArea.setText(textStr);
 doom-2015-10-30 15:30:11 */
/* doom-2015-10-30 15:34:33 
			Iterator it = mFuncLCDTimingCache.keySet().iterator();
			int lcdtimingLength = mLCDTimingItems.length;
			String[] dataGroup = String[lcdtimingLength];
			int index = 0;
			while(it.hasNext()) {
				String key = (String)it.next();
				dataGroup[index++] = mFuncLCDTimingCache.get(key);
			}
 doom-2015-10-30 15:34:33 */
 			mTextFieldGroup.pushDataGroup(mFuncLCDTimingCache);

			mEditAreaScrollPane.setVisible(false);
			mTextFieldGroup.setVisible(true);
		}else{
			String textStr = (mFuncCache[item] != null) ? mFuncCache[item] : "";
			mEditArea.setText(textStr);
			
			mEditAreaScrollPane.setVisible(true);
			mTextFieldGroup.setVisible(false);
		}
	}
		
	private int getSelectedItem(String action){
		for(int index = 0; index < mFuncTitleList.length; index++){ 
			if(mFuncTitleList[index].equals(action)){
				return index;
			}
		}		
		for(int index = 0; index < mOperationTitleList.length; index++){ 
			if(mOperationTitleList[index].equals(action)){
				return mFuncTitleList.length + index;
			}
		}
		return -1;
	}

	private void operationHandler(int index){
		switch(index){
			case 0:
				Log.d(TAG, "operationHandler OPEN");
				openFileHandler();
				break;
			case 1:
				Log.d(TAG, "operationHandler SAVE");
				saveFileHandler();
				break;
			case 2:
				Log.d(TAG, "operationHandler SAVE AS");
				saveAsFileHandler();			
				break;
			case 3:
				Log.d(TAG, "operationHandler RUN");
				runHandler();
				break;
			case 4:
				Log.d(TAG, "operationHandler SEND");
				sendHandler();
				break;
/*
			case 0:
				Log.d(TAG, "operationHandler OPEN");
				openFileHandler();
				break;
			case 1:
				Log.d(TAG, "operationHandler CLOSE");
				closeFileHandler();
				break;
			case 2:
				Log.d(TAG, "operationHandler SAVE");
				saveFileHandler();
				break;
			case 3:
				Log.d(TAG, "operationHandler SAVE AS");
				saveAsFileHandler();
				break;
			case 4:
				Log.d(TAG, "operationHandler SEND ALL");
				sendAllHandler();
				break;
*/
			default:
				break;
		}
	}

	public void actionPerformed(ActionEvent e) {
/* doom-2015-10-29 18:26:39 
		Log.d(TAG, "actionPerformed e.getActionCommand(): "+ e.getActionCommand());
 doom-2015-10-29 18:26:39 */
		int index = getSelectedItem(e.getActionCommand());
/* doom-2015-10-29 18:26:40 
		Log.d(TAG, "actionPerformed index: "+ index);
 doom-2015-10-29 18:26:40 */

		if(index != -1 && index < (mFuncTitleList.length - 2)){
			/* save cache data */
			saveCacheData();
		
			setFuncSelectedItem(index);
		}else if(index == (mFuncTitleList.length - 1)
			|| index == (mFuncTitleList.length - 2)){
			saveCacheData();
			
			setFuncSelectedItem(index);
		}else if(index != -1 && index >= mFuncTitleList.length){
			saveCacheData();
			
			operationHandler(index - mFuncTitleList.length);
		}
	}

      private void loadFileHandler(String fileName){
		Log.d(TAG, "loadFileHandler fileName:"+fileName);
		try {  
			SAXBuilder builder = new SAXBuilder();  
			Document document = builder.build(fileName);  
			Element root = document.getRootElement();  
			List rootPros = root.getChildren();
			
			if((mFuncTitleList.length - 2) != rootPros.size()){ // 
				Log.d(TAG, "loadFileHandler mFuncTitleList ERROR !" ); 
				setEmptyCache();
				return;
			}
			mFuncCache = new String[mFuncTitleList.length/*rootPros.size()*/];
			
			for (int i = 0; i < rootPros.size(); i++) {  
				Element child = (Element) rootPros.get(i);  
				
				List pros = child.getChildren();  
				if(pros == null || pros.size() == 0)
				{
/* doom-2015-11-2 17:40:19 
					Log.d("", child.getName() + ":" + child.getValue()); 
 doom-2015-11-2 17:40:19 */
					mFuncCache[i] = child.getValue();
				}else{
/* doom-2015-11-2 17:40:27 
					Log.d("", child.getName() + ":" );
 doom-2015-11-2 17:40:27 */
					mFuncCache[i] = "";
					if(child.getName().equals("LCDTiming")){
						if(mLCDTimingItems.length == pros.size()){
						  	mFuncLCDTimingCache = new String[mLCDTimingItems.length]; 
							for (int j = 0; j < pros.size(); j++) {  
								Element element = (Element) pros.get(j);  
/* doom-2015-11-2 17:40:32 
								Log.d("", element.getName() + ":" + element.getValue());  
 doom-2015-11-2 17:40:32 */
								mFuncLCDTimingCache[j] = element.getValue();
/* doom-2015-10-30 15:40:9 
								mFuncLCDTimingCache.put(element.getName(), element.getValue());
 doom-2015-10-30 15:40:9 */
							} 
						}
						else{
							Log.d(TAG, "loadFileHandler LCDTiming ERROR !" ); 
							setEmptyCache();
							return;
						}
					}
				}

				Log.d("", "\n" ); 
			}  

			/* update data to views */
			setFuncSelectedItem(mFuncSelectedItem);
			
		} catch (Exception e) {  
			e.printStackTrace();  

			setEmptyCache();
		}  		
      }

	private void setEmptyCache(){
		mFuncCache = new String[mFuncTitleList.length];
		mFuncLCDTimingCache = new String[mLCDTimingItems.length]; 
		setFuncSelectedItem(mFuncSelectedItem);
	}

	private void saveCacheData(){
		if(mFuncTitleList[mFuncSelectedItem].equals("LCDTiming")){
 			mFuncLCDTimingCache = mTextFieldGroup.pullDataGroup();
		}else{
			mFuncCache[mFuncSelectedItem] = mEditArea.getText();		
		}
	}

	private void openFileHandler(){
		CustomProperties cp = new CustomProperties(CustomProperties.USER_DIR_DEFAULT, "");		
		JFileChooser fd = new JFileChooser(cp.getConfigPropertiesRootDir());  
		fd.showOpenDialog(this);  
		File f = fd.getSelectedFile();  
		if(f != null){
			Log.d(TAG, "openFileHandler f.getAbsolutePath(): "+ f.getAbsolutePath());
			mCurrentOpenFile = f.getAbsolutePath();
			mCurrentOpenFileLabel.setText("[Current open file: " + mCurrentOpenFile+"]");
			mProperties.writeValue("current_open_file", mCurrentOpenFile);
			mProperties.readValue("current_open_file");
			loadFileHandler(f.getAbsolutePath());
		}  
	}

	private void closeFileHandler(){
		mCurrentOpenFile = "";
		mCurrentOpenFileLabel.setText("[Current open file: " + mCurrentOpenFile+"]");
		setEmptyCache();
	}

	private void saveFileHandler(){    
		/* save cache data */
		saveCacheData();
		
		if(mCurrentOpenFile != null && !mCurrentOpenFile.equals("")){
			try{
				buildLCDPanelXML(mCurrentOpenFile);
			} catch (Exception e) {  
				e.printStackTrace();  
			}  	
		}else{
			String ret = saveAsFileHandler();
			if(ret != null){
				Log.d(TAG, "saveAsFileHandler reload");
				mCurrentOpenFile = ret;
				mCurrentOpenFileLabel.setText("[Current open file: " + mCurrentOpenFile+"]");
				mProperties.writeValue("current_open_file", mCurrentOpenFile);
				mProperties.readValue("current_open_file");
				loadFileHandler(ret);	
			}
		}
	}

	private String saveAsFileHandler(){
		/* save cache data */
		saveCacheData();
		
		CustomProperties cp = new CustomProperties(CustomProperties.USER_DIR_DEFAULT, "");	
		JFileChooser chooser = new JFileChooser(cp.getConfigPropertiesRootDir());
		chooser.showSaveDialog(this);
		File f = chooser.getSelectedFile();	
		if(f != null){
			Log.d(TAG, "saveAsFileHandler f.getAbsolutePath(): "+ f.getAbsolutePath());
			try{
				buildLCDPanelXML(f.getAbsolutePath());
				return f.getAbsolutePath();
			} catch (Exception e) {  
				e.printStackTrace();  
				return null;
			}  			
		}else{
			return null;
		}
/* doom-2015-10-29 18:6:45 
		try{
			buildLCDPanelXML();
		} catch (Exception e) {  
			e.printStackTrace();  
		}  
 doom-2015-10-29 18:6:45 */
	}
/* doom-2015-10-29 18:15:58 
CustomProperties.getConfigPropertiesFilePath(LCDPanelXML)
 doom-2015-10-29 18:15:58 */

	private void sendAllHandler(){
		saveFileHandler();	
		if(writeBatchToFile(generateBatchStr())){
			adbCmdExec(AndroidDeviceManager.getBatchCmd(AndroidDeviceManager.getBatchPath()));
		}
/* doom-2015-11-4 15:21:11 
		if(writeBatchToFile(generateBatchStr())){
			adbCmdExec(AndroidDeviceManager.getBatchCmd(AndroidDeviceManager.getBatchPath()));
		}
 doom-2015-11-4 15:21:11 */
	}

	private void runHandler(){
		Log.d(TAG, "runHandler mFuncSelectedItem:"+mFuncSelectedItem);
		if(mFuncSelectedItem == (mFuncTitleList.length -1)){
			logExportToTextArea();
		}
		if(writeBatchToFile(generateSingleCommandStr())){
			adbCmdExec(AndroidDeviceManager.getBatchCmd(AndroidDeviceManager.getBatchPath()));
		}		
	}

	private void sendHandler(){
		sendAllHandler();
	}

	public void buildLCDPanelXML(String saveFileName) throws IOException, JDOMException {   
		
		Element root = new Element("Root");   
		Document Doc = new Document(root);   

		int funcCacheLength = mFuncCache.length;
		int funcTitleListLength = mFuncTitleList.length;
		if(funcCacheLength != funcTitleListLength){
			Log.d(TAG, "buildLCDPanelXML funcTitleListLength:"+funcTitleListLength+"funcCacheLength :"+funcCacheLength);
			return;
		}

		for(int index = 0; index < mFuncTitleList.length; index++){ 
			if(index == mFuncTitleList.length - 1 ||
				index == mFuncTitleList.length -2){
				break;
			}
			Element elements = new Element(mFuncTitleList[index]);     
/*			if(!mFuncCache[index].equals("")){
				elements.setText(mFuncCache[index]);
			}else*/
			{
				if(mFuncTitleList[index].equals("LCDTiming")){
					for(int k = 0; k < mFuncLCDTimingCache.length; k++){
						elements.addContent(new Element(mLCDTimingItems[k]).setText((mFuncLCDTimingCache[k] != null) ? mFuncLCDTimingCache[k] : ""));  
					}
/* doom-2015-10-30 15:38:8 
					Iterator it = mFuncLCDTimingCache.keySet().iterator();
					while(it.hasNext()) {
						String key = (String)it.next();
						elements.addContent(new Element(key).setText(mFuncLCDTimingCache.get(key)));  
					}
 doom-2015-10-30 15:38:8 */
				}else{
					elements.setText((mFuncCache[index] != null) ? mFuncCache[index] : "");
				}
			}
			root.addContent(elements);			
		}

		
/* doom-2015-10-30 10:26:18 
		Element elements = new Element("Version").setText("\n1.1\n");     
		root.addContent(elements);

		elements = new Element("LCDTiming");     
		elements.addContent(new Element("HSA").setText("1080"));  
		elements.addContent(new Element("VSA").setText("1920"));  
		elements.addContent(new Element("MODE").setText("0"));  
		
		elements.addContent(new Element("LANE").setText("4"));  
		elements.addContent(new Element("VSYNC").setText("2"));  
		elements.addContent(new Element("VBP").setText("6"));  
		elements.addContent(new Element("VFP").setText("8"));  
		elements.addContent(new Element("HSYNC").setText("10"));  
		
		elements.addContent(new Element("HBP").setText("40"));  
		elements.addContent(new Element("HFP").setText("60"));  
		elements.addContent(new Element("DIV1").setText("1"));  
		elements.addContent(new Element("DIV2").setText("1"));  
		elements.addContent(new Element("DIV").setText("45"));  
		root.addContent(elements);

		elements = new Element("IDSetting").setText("\n{0x00022902,0x000000B0,0x01};\n");     
		root.addContent(elements);

		elements = new Element("LCDSuspend").setText("\n{129,1,5};\n{131,0,120};\n{125,0,5};\n{126,0,10};\n");     
		root.addContent(elements);
 doom-2015-10-30 10:26:18 */

		Format format = Format.getPrettyFormat();
		XMLOutputter XMLOut = new XMLOutputter(format);
		XMLOut.output(Doc, new FileOutputStream(saveFileName));
	} 	

	private void adbCmdExec(String cmdStr){

		if(mCodeEditorMain != null){
			String deviceName = mCodeEditorMain.getConnectedDevice();
			if(deviceName == null || deviceName.equals("")){
				Log.d(TAG, "adbCmdExec CAN'T FIND ANY DEVICE");
				return;
			}
		}
		
		try {			
			Process process = Runtime.getRuntime().exec(cmdStr);  
			
			final BufferedReader batchInputStream = new BufferedReader(new InputStreamReader(process.getInputStream()));
			final  BufferedReader  batchErrorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
			
			new Thread(new Runnable() {
				String line;
				public void run() {
					try {
						while((line=batchErrorReader.readLine()) != null) {
							Log.d("Err", line);	       		        
						}
					} catch (IOException e) {
						e.printStackTrace();  
					}
				}
			}).start();
			
			new Thread(new Runnable() {
				String line;
				public void run() {
					try {
						while((line=batchInputStream.readLine()) != null) {
							Log.d("", line);	       	
						}
					} catch (IOException e) {
						e.printStackTrace();  
					}
				}
			}).start();
			
			int i = process.waitFor();
		} catch (Exception e) {
			e.printStackTrace();
		}	
	}	

	private String generateCacheLineStr(String srcStr){
		String dstStr = srcStr;
		dstStr = srcStr.replaceAll("\\s*", "");

		dstStr = dstStr.replace("};{", "/");
		dstStr = dstStr.replace("{", "");
		dstStr = dstStr.replace("};", "");
		
		dstStr = dstStr.replace(",", "-");
		//dstStr = dstStr.replace(";", "/");
		
		Log.d(TAG, "generateCacheLineStr dstStr:"+dstStr);
		return dstStr;
	}
	private String[] getSplitStrList(String srcStr){
		if(srcStr == null){
			Log.d(TAG, "getSplitStrList ERROR CODE 1");
			return null;
		}
		String dstStr = srcStr;
		dstStr = srcStr.replaceAll("\\s*", "");		
		String[] srcStrList = dstStr.split(";");
		int srcStrLenght = srcStrList.length;
		Log.d(TAG, "getSplitStrList srcStrLenght:"+srcStrLenght+" mSingleFileMaxLine:"+mSingleFileMaxLine+" mSplitFileCount:"+mSplitFileCount);
		if(srcStrLenght > (mSingleFileMaxLine * mSplitFileCount)){
			Log.d(TAG, "getSplitStrList ERROR CODE 2");
			return null;
		}		
		int dstStrListLength = ((srcStrLenght % mSingleFileMaxLine) > 0) ? ((srcStrLenght / mSingleFileMaxLine) + 1) : (srcStrLenght / mSingleFileMaxLine);
		Log.d(TAG, "getSplitStrList dstStrListLength:"+dstStrListLength);
		String[] dstStrList = new String[dstStrListLength];

		for(int index = 0; index < srcStrList.length; index++){
			if((index % mSingleFileMaxLine) == 0)
				dstStrList[(index / mSingleFileMaxLine)]="";
			else
				dstStrList[(index / mSingleFileMaxLine)]+= srcStrList[index];  
		}
		for(int dstIndex = 0; dstIndex < dstStrList.length; dstIndex++){		
			dstStrList[dstIndex] = dstStrList[dstIndex].replace("}{", "/");
			dstStrList[dstIndex] = dstStrList[dstIndex].replace("{", "");
			dstStrList[dstIndex] = dstStrList[dstIndex].replace("}", "");			
			dstStrList[dstIndex] = dstStrList[dstIndex].replace(",", "-");	
			Log.d(TAG, "getSplitStrList dstIndex:"+dstIndex+" dstStrList[dstIndex]:"+dstStrList[dstIndex]);			
		}

		return dstStrList;
	
	}
	private String generateSingleCommandStr(){
		LCDPANEL_DRIVER_PATH = mTestDriverFilePath.getText();
		if(LCDPANEL_DRIVER_PATH == null || LCDPANEL_DRIVER_PATH.equals("")){
			LCDPANEL_DRIVER_PATH = TEST_DRIVER_DEFAULT;
		}
		
		String batchStr = "";
		String adbPath = AndroidDeviceManager.getAdbPath();
		
		int index = mFuncSelectedItem;
		if(index < 0 || index > mFuncTitleList.length)
			return batchStr;
		if(!mFuncTitleList[index].equals("LCDTiming")){
			if(mFuncTitleList[index].equals("LCDinit"))
			{
				//int size = mFuncCache[index].length();
				//Log.d(TAG, "LCDinit mFuncCache[index]:"+mFuncCache[index]+" size:"+size);
				String[] lcdInitList = getSplitStrList(mFuncCache[index]);
				for(int initIndex = 0; initIndex < lcdInitList.length; initIndex++){
					batchStr += adbPath +" shell \"echo " + lcdInitList[initIndex] + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index]  + (initIndex+1)+ "\"";
					batchStr += AndroidDeviceManager.getLineSeparator();
				}				
				//batchStr = adbPath +" shell \"echo " + generateCacheLineStr((mFuncCache[index] != null) ? mFuncCache[index] : "") + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index] + "\"";
			}
			else if(mFuncTitleList[index].equals("HSwrite"))
			{
				String[] lcdInitList = getSplitStrList(mFuncCache[index]);
				for(int initIndex = 0; initIndex < lcdInitList.length; initIndex++){
					batchStr += adbPath +" shell \"echo " + lcdInitList[initIndex] + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index]  + (initIndex+1)+ "\"";
					batchStr += AndroidDeviceManager.getLineSeparator();
				}			
				//batchStr = adbPath +" shell \"echo " + generateCacheLineStr((mFuncCache[index] != null) ? mFuncCache[index] : "") + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index] + "\"";
			}
			else if(mFuncTitleList[index].equals("HSread"))
			{
				batchStr = adbPath +" shell \"echo " + generateCacheLineStr((mFuncCache[index] != null) ? mFuncCache[index] : "") + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index] + "\"";
			}			
			else{
				batchStr = adbPath +" shell \"echo " + generateCacheLineStr((mFuncCache[index] != null) ? mFuncCache[index] : "") + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index] + "\"";					
			}
		}else{
			String lcdtimingStr = "";
			for(int k = 0; k < mLCDTimingItems.length; k++){
				if(k > 0)
					lcdtimingStr += ("-"+mFuncLCDTimingCache[k]);
				else
					lcdtimingStr += mFuncLCDTimingCache[k];
			}
			batchStr = adbPath +" shell \"echo " + lcdtimingStr + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index] + "\"";
		}
		
		return batchStr;
	}
	
	private String generateBatchStr(){	

		LCDPANEL_DRIVER_PATH = mTestDriverFilePath.getText();
		if(LCDPANEL_DRIVER_PATH == null || LCDPANEL_DRIVER_PATH.equals("")){
			LCDPANEL_DRIVER_PATH = TEST_DRIVER_DEFAULT;
		}
		
		String batchStr = "";
		String adbPath = AndroidDeviceManager.getAdbPath();
		for(int index = 0; index < mFuncTitleList.length; index++){
			if(index == mFuncTitleList.length - 1 ||
				index == mFuncTitleList.length -2){
				break;
			}			
			if(!mFuncTitleList[index].equals("LCDTiming")){
				if(mFuncTitleList[index].equals("LCDinit"))
				{
					//int size = mFuncCache[index].length();
					//Log.d(TAG, "LCDinit mFuncCache[index]:"+mFuncCache[index]+" size:"+size);
					String[] lcdInitList = getSplitStrList(mFuncCache[index]);
					for(int initIndex = 0; initIndex < lcdInitList.length; initIndex++){
						batchStr += adbPath +" shell \"echo " + lcdInitList[initIndex] + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index]  + (initIndex+1)+ "\"";
						batchStr += AndroidDeviceManager.getLineSeparator();						
					}
				}
				else{
					batchStr += adbPath +" shell \"echo " + generateCacheLineStr((mFuncCache[index] != null) ? mFuncCache[index] : "") + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index] + "\"";					
				}
			}else{
				String lcdtimingStr = "";
				for(int k = 0; k < mLCDTimingItems.length; k++){
					if(k > 0)
						lcdtimingStr += ("-"+mFuncLCDTimingCache[k]);
					else
						lcdtimingStr += mFuncLCDTimingCache[k];
				}
				batchStr += adbPath +" shell \"echo " + lcdtimingStr + " > " + LCDPANEL_DRIVER_PATH + mFuncTitleList[index] + "\"";
			}
			batchStr += AndroidDeviceManager.getLineSeparator();
		}
		return batchStr;
	}
	private boolean writeBatchToFile(String batchStr){
		try{
			String batchFile = AndroidDeviceManager.getBatchPath();
			File file =new File(batchFile);
			if(!file.exists()){
				file.createNewFile();
			}
			
			FileWriter fileWritter = new FileWriter(batchFile);
			BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
			bufferWritter.write(batchStr);
			bufferWritter.close();
			return true;
		}catch(IOException e){
			return false;
		}	
	}
	
}
